package cn.haocxy.jfm.gui;

import java.util.function.Predicate;

import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.stage.Window;
import cn.haocxy.jfm.file.FilePath;
import cn.haocxy.jfm.filelist.FileList;

/**
 * 
 * <p>在文件项上打开的菜单的基类
 * 
 * <p>由该基类控制菜单的打开和关闭的逻辑以及与文件项视图的交互.
 * <p>该类的具体子类控制菜单的内容和功能.
 * <p>由FileItemMenuManager控制要打开哪个菜单.
 * @author 蔡心宇
 *
 */
abstract class FileItemMenu {

	private static final FileItemMenuManager manager = new FileItemMenuManager();
	
	private final ContextMenu menu = new ContextMenu();
	
	private IconArea iconArea = null;
	
	private boolean shown = false;
	
	private Runnable onShown = null;
	
	private Runnable onHidden = null;
	
	private int cnt;
	
	private int sepcnt = 0;
	
	public FileItemMenu() {
		
		menu.setOnShown(e->{
			shown = true;
			callOnShown();
		});
		
		menu.setOnHidden(e->{
			shown = false;
			callOnHidden();
		});
		
	}
	
	private void callOnShown() {
		if (iconArea != null && onShown != null) {
			onShown.run();
		}
	}
	
	private void callOnHidden() {
		if (iconArea != null && onHidden != null) {
			onHidden.run();
		}
	}
	protected void filt() {
	}
	
	protected void filt(MenuItem item, Predicate<MenuItem> filter) {
		if (item == null || filter == null) {
			return;
		}
		if (filter.test(item)) {
			item.setVisible(true);
		} else {
			--cnt;
			item.setVisible(false);
		}
	}
	
	protected void filtSep(MenuItem item, Predicate<MenuItem> filter) {
		if (item == null || filter == null) {
			return;
		}
		if (filter.test(item)) {
			item.setVisible(true);
		} else {
			item.setVisible(false);
		}
	}
	
	protected FileList getFileList() {
		return getIconArea().getFileItem().getFileListModel();
	}
	
	protected FilePath getItemPath() {
		FilePath path = getIconArea().getFileItem().toFilePath();
		return path;
	}
	
	protected Window getCurrentWindow() {
		Window w = getIconArea().toNode().getScene().getWindow();
		return w;
	}
	
	protected MenuItem add(String text, Runnable action) {
		MenuItem item = new MenuItem(text);
		if (action != null) {
			item.setOnAction(e->action.run());
		}
		menu.getItems().add(item);
		return item;
	}
	
	protected MenuItem addSep() {
		++sepcnt;
		MenuItem sep = new SeparatorMenuItem();
		menu.getItems().add(sep);
		return sep;
	}
	
	public void setOnShown(Runnable action) {
		this.onShown = action;
	}
	
	public void setOnHidden(Runnable action) {
		this.onHidden = action;
	}
	
	public IconArea getIconArea() {
		return iconArea;
	}
	
	public void show(IconArea iconArea, Node node, double screenX, double screenY) {
		this.iconArea = iconArea;
		cnt = menu.getItems().size() - sepcnt;
		filt();
		if (cnt == 0) {
			callOnHidden();
			return;
		}
		menu.show(node, screenX, screenY);
	}
	
	public void hide() {
		menu.hide();
	}
	
	public boolean shown() {
		return shown;
	}
	
	public boolean hidden() {
		return !shown;
	}
	
	public static void showMenu(IconArea iconArea, Node node, double screenX, double screenY) {
		manager.showMenu(iconArea, node, screenX, screenY);
	}
	
	public static void hideMenu() {
		manager.hideMenu();
	}
	
	public static boolean isShown() {
		return manager.shown();
	}
}
